module how.poker {
	/**
	 * 牌列表，下面有此自定义控件的使用示例
	 * @author 袁浩 
     * @event how.poker.CardList.POPUPED_COMPLETE 当开始选择牌时
     * @event how.poker.CardList.SELECT_START 当开始选择牌时
     * @event how.poker.CardList.SELECT_COMPLETE 当完成选择牌时
     * @event how.poker.CardList.DRAG_START 当开始拖动牌时
     * @event how.poker.CardList.DRAG_COMPLETE 当结束拖动牌时
	 * @example 使用方式很简单，只需要设置一个数据源和项皮肤即可。项的皮肤至少需要有up、down、popup、popupAndDown这4种状态，以下为项的皮肤代码：
<pre>
<?xml version='1.0' encoding='utf-8'?>
<e:Skin class="CardItemSkin" states="up,down,disabled,popup,popupAndDown" xmlns:e="http://ns.egret.com/eui" height="108">
    <e:Image source="{data.cardData}" width="67" height="88" y.popup="0" y.popupAndDown="0" y="20"/>
    <e:Rect height="88" width="67" y="20" visible.down="true" visible.popupAndDown="true" y.popupAndDown="0" fillColor="0x444444" fillAlpha="0.4" visible="false"/>
</e:Skin>
</pre>
	 */
    export class CardList extends eui.List {
        /**
         * 当弹起变化时
         */
        public static POPUP_CHANGED: string = "popupChanged";
        /**
         * 当开始选择牌时
         */
        public static SELECT_START: string = "selectStart";
        /**
         * 当完成选择牌时
         */
        public static SELECT_COMPLETE: string = "selectComplete";
        /**
         * 当开始拖动牌时
         */
        public static DRAG_START: string = "dragStart";
        /**
         * 当结束拖动牌时
         */
        public static DRAG_COMPLETE: string = "dragComplete";
        /**
         * 开始触摸的坐标
         */
        protected beginTouchPoint: egret.Point = new egret.Point();
        /**
         * 是否开始触摸
         */
        protected isBeginTouch: boolean;
        /**
         * 是否可以开始拖动
         */
        protected canBeginDrag: boolean;
        /**
         * 点击空白处时是否取消所有弹起的牌
         */
        public unPopUpIndicesEnabled: boolean = true;
        /**
         * 空白处遇到哪些类型就不取消弹起
         */
        public unPopUpIndicesTargetType: any[] = [eui.Button];
        private _isDraging: boolean = false;
        /**
         * 是否正在拖动
         */
        public get isDraging(): boolean {
            return this._isDraging;
        }
        /**
         * 选择框显示对象
         */
        public selectedRect: eui.Rect = new eui.Rect();
        /**
         * 选择框是否显示
         */
        public selectedRectVisibility: boolean = false;
        private _popupedIndices: Array<number> = [];
        /**
         * 如果项已经弹起，再次需要弹起他的时候，是否取消此项的弹起状态
         */
        public popupReversed: boolean = true;
        /**
         * 如果项已经弹起，此次不需要弹起他的时候，是否取消此项的弹起状态
         */
        public removeOldPopup: boolean = false;
        /**
         * 弹起的牌是否可以拖拽
         */
        public dragEnabled: boolean = false;
        /**
         * 拖拽是否有一个牌列表
         */
        public dragListEnabled: boolean = true;
        /**
         * 弹起的牌是否可以拖拽方式来打出
         */
        public dragPutEnabled: boolean = true;
        /**
         * 所有弹起的项索引
         */
        public get popupedIndices(): Array<number> {
            return this._popupedIndices;
        }
        /**
         * 所有弹起的项
         */
        public get popupedItems(): Array<any> {
            var popupedItems: Array<any> = [];
            for (var i = 0; i < this.popupedIndices.length; i++) {
                popupedItems.push(this.dataProvider.getItemAt(this.popupedIndices[i]));
            }
            return popupedItems;
        }
        /**
         * 所有弹起的项
         */
        public set popupedItems(data: Array<any>) {
            this.setPopUpIndices();
            data = data || [];
            var indexs: number[] = [];
            for (var i: number = 0; i < data.length; i++) {
                indexs.push(this.dataProvider.getItemIndex(data[i]));
            }
            this.setPopUpIndices(indexs);
        }
        /**
         * 拖动的牌列表
         */
        public dragList: eui.List;
        /**
         * 牌列表
         */
        public constructor() {
            super();
            this.selectedRect.strokeWeight = 1;
            this.selectedRect.fillColor = 0xFFFF00;
            this.selectedRect.fillAlpha = 0.2;
            this.touchChildren = false;
            this.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchBegin, this);
            this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddedFromStage, this);
            this.addEventListener(egret.Event.REMOVED_FROM_STAGE, this.onRemovedFromStage, this);
        }
        private onAddedFromStage(event: egret.Event): void {
            this.selectedRect.visible = false;
            this.stage.addChild(this.selectedRect);
            this.stage.addEventListener(egret.TouchEvent.TOUCH_END, this.onStageTouchEnd, this);
            this.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.onStageTouchMove, this);
            this.stage.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onStageTouchTab, this);
        }
        private onRemovedFromStage(event: egret.Event): void {
            if (this.dragList && this.dragList.parent) {
                this.stage.removeChild(this.dragList);
            }
            this.stage.removeChild(this.selectedRect);
            this.stage.removeEventListener(egret.TouchEvent.TOUCH_END, this.onStageTouchEnd, this);
            this.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE, this.onStageTouchMove, this);
            this.stage.removeEventListener(egret.TouchEvent.TOUCH_TAP, this.onStageTouchTab, this);
        }
        /**
         * 当触摸开始时
         * @param event 事件对象
         */
        protected onTouchBegin(event: egret.TouchEvent): void {
            this.canBeginDrag = false;
            for (var i = 0; i < this.numElements; i++) {
                var item: eui.ItemRenderer = <eui.ItemRenderer>this.getElementAt(i);
                if (item && item.hitTestPoint(event.stageX, event.stageY) && (item.currentState == "popup" || item.currentState == "popupAndDown")) {
                    this.canBeginDrag = true && this.dragEnabled;
                    break;
                }
            }
            if (!this.isBeginTouch) {
                this.beginTouchPoint.x = event.stageX;
                this.beginTouchPoint.y = event.stageY;
                this.isBeginTouch = true;
            }
        }
        /**
         * 当舞台触摸移动时
         * @param event
         */
        protected onStageTouchMove(event: egret.TouchEvent): void {
            if (this._isDraging && this.dragListEnabled) {
                this.setDragListTransform(event.stageX, event.stageY);
            }
            if (!this.isBeginTouch) {
                return;
            }
            this.setCardsInSelectRectangle(event.stageX, event.stageY);
            if (!this._isDraging && this.canBeginDrag && !this.hitTestPoint(event.stageX, event.stageY)) {//如果可以开始拖动并且触摸点已经不在列表
                this.canBeginDrag = false;
                this.isBeginTouch = false;
                this._isDraging = true;
                this.selectedRect.visible = false;
                for (var i = 0; i < this.numElements; i++) {
                    var item: eui.ItemRenderer = <eui.ItemRenderer>this.getElementAt(i);
                    if (item) {
                        if (item.currentState == "popup" || item.currentState == "popupAndDown") {
                            item.currentState = "popupAndDown";
                        }
                        else {
                            item.currentState = "up";
                        }
                    }
                }
                if (this.dragListEnabled) {
                    this.addDragList(event.stageX, event.stageY);
                }
            }
        }
        /**
         * 添加拖动列表
         */
        public addDragList(x: number, y: number): void {
            this.dragList = new eui.List();
            this.dragList.touchChildren = this.dragList.touchEnabled = false;
            this.dragList.itemRendererSkinName = this.itemRendererSkinName;
            this.dragList.itemRenderer = this.itemRenderer;
            this.dragList.dataProvider = new eui.ArrayCollection(this.popupedItems);
            this.dragList.layout = this.layout;
            this.setDragListTransform(x, y);
            this.stage.addChild(this.dragList);
        }
        /**
         * 设置拖动列表的位置
         */
        public setDragListTransform(x: number, y: number): void {
            if (this.dragList) {
                this.dragList.x = x - this.dragList.width / 2;
                this.dragList.y = y - this.dragList.height / 2;
            }
        }
        /**
         * 当舞台触摸时
         * @param event
         */
        protected onStageTouchTab(event: egret.TouchEvent): void {
            var canUnPop: boolean = true;
            for (var i = 0; i < this.unPopUpIndicesTargetType.length; i++) {
                if (event.target instanceof this.unPopUpIndicesTargetType[i]) {
                    canUnPop = false;
                }
            }
            if (!this.hitTestPoint(event.stageX, event.stageY) && this.unPopUpIndicesEnabled && canUnPop) {
                this.setPopUpIndices(null);
            }
        }
        /**
         * 当舞台触摸结束时
         * @param event
         */
        protected onStageTouchEnd(event: egret.TouchEvent): void {
            if (this.isDraging) {
                if (this.dragList) {
                    this.stage.removeChild(this.dragList);
                    if (this.dragPutEnabled) {
                        this.dispatchEventWith(CardList.DRAG_COMPLETE, false, (this.dragList.dataProvider as eui.ArrayCollection).source);
                    }
                    this.dragList = null;
                }
                this._isDraging = false;
                this.isBeginTouch = false;
            }
            else if (!this.isBeginTouch) {
                return;
            }
            else {
                this.isBeginTouch = false;
                this.setCardsInSelectRectangle(event.stageX, event.stageY);
            }
        }
        /**
         * 设置含在选择范围的牌
         */
        public setCardsInSelectRectangle(endTouchX: number, endTouchY: number): void {
            this.allowMultipleSelection = true;
            var selectedRectangle: egret.Rectangle = this.getSelectedRectangle(endTouchX, endTouchY);
            var itemRectangle: egret.Rectangle = new egret.Rectangle();
            var selectedIndices: Array<number> = [];
            for (var i = 0; i < this.numElements; i++) {
                var item: eui.ItemRenderer = <eui.ItemRenderer>this.getElementAt(i);
                if (item) {
                    var itemGlobalPoint: egret.Point = item.localToGlobal();
                    itemRectangle.x = itemGlobalPoint.x;
                    itemRectangle.y = itemGlobalPoint.y;
                    itemRectangle.width = item.width + (i == this.numElements - 1 ? 0 : this.hgap);
                    itemRectangle.height = item.height + (i == this.numElements - 1 ? 0 : this.vgap);
                    if (selectedRectangle.intersects(itemRectangle)) {
                        selectedIndices.push(i);
                    }
                }
            }
            this.selectedIndex = -1;
            if (this.isBeginTouch) {
                this.setSelectedIndices(selectedIndices);
            }
            else {
                this.setPopUpIndices(selectedIndices);
            }
        }
        /**
         * 设置多个选中项
         * @param value 选中项索引的数组
         * @param dispatchChangeEvent 是否派发changed事件
         */
        protected setSelectedIndices(value: number[], dispatchChangeEvent?: boolean): void {
            super.setSelectedIndices(value, dispatchChangeEvent);
            for (var i = 0; i < this.numElements; i++) {
                var item: eui.ItemRenderer = <eui.ItemRenderer>this.getElementAt(i);
                if (item) {
                    if (value.indexOf(i) != -1) {
                        if (item.currentState == "popup" || item.currentState == "popupAndDown") {
                            item.currentState = "popupAndDown";
                        }
                        else {
                            item.currentState = "down";
                        }
                    }
                    else {
                        if (item.currentState == "popupAndDown") {
                            item.currentState = "popup";
                        }
                        else if (item.currentState == "down") {
                            item.currentState = "up";
                        }
                    }
                }
            }
        }
        /**
         * 设置弹起的项
         * @param value 选中项索引的数组，如果为空或者长度为0的数组则取消所有弹起的项
         */
        public setPopUpIndices(value: number[] = null): void {
            value = value || [];
            this.setSelectedIndex(-1);
            this._popupedIndices = [];
            for (var i = 0; i < this.numElements; i++) {
                var item: eui.ItemRenderer = <eui.ItemRenderer>this.getElementAt(i);
                if (item) {
                    if (value.indexOf(i) != -1) {
                        if ((item.currentState == "popup" || item.currentState == "popupAndDown") && this.popupReversed) {
                            item.currentState = "up";
                        }
                        else {
                            item.currentState = "popup";
                            this._popupedIndices.push(i);
                        }
                    }
                    else {
                        if ((item.currentState == "popup" || item.currentState == "popupAndDown") && !this.removeOldPopup && value && value.length > 0) {
                            item.currentState = "popup";
                            this._popupedIndices.push(i);
                        }
                        else {
                            item.currentState = "up";
                        }
                    }
                }
            }
            this.dispatchEventWith(CardList.POPUP_CHANGED, false, value);
        }
        /**
         * 布局的横向间隔
         */
        protected get hgap(): number {
            if (egret.is(this.layout, "eui.HorizontalLayout")) {
                return (<eui.HorizontalLayout>this.layout).gap;
            }
            return 0;
        }
        /**
         * 布局的纵向间隔
         */
        protected get vgap(): number {
            if (egret.is(this.layout, "eui.VerticalLayout")) {
                return (<eui.VerticalLayout>this.layout).gap;
            }
            return 0;
        }
        /**
         * 获取选择范围
         * @param endTouchX 当前触摸点横坐标
         * @param endTouchY 当前触摸点纵坐标
         * @returns 选择范围
         */
        public getSelectedRectangle(endTouchX: number, endTouchY: number): egret.Rectangle {
            var rectangle: egret.Rectangle = new egret.Rectangle(
                Math.min(this.beginTouchPoint.x, endTouchX),
                Math.min(this.beginTouchPoint.y, endTouchY),
                Math.abs(this.beginTouchPoint.x - endTouchX),
                Math.abs(this.beginTouchPoint.y - endTouchY));
            this.renderSelectedRect(rectangle);
            return rectangle;
        }
        /**
         * 渲染选择框
         * @param rectangle 选择框的选择范围
         */
        protected renderSelectedRect(rectangle: egret.Rectangle): void {
            this.selectedRect.visible = this.isBeginTouch && this.selectedRectVisibility;
            this.selectedRect.x = rectangle.x;
            this.selectedRect.y = rectangle.y;
            this.selectedRect.width = rectangle.width;
            this.selectedRect.height = rectangle.height;
        }
    }
}
